class IP4Address:
    def __init__(self, *parts):
        if isinstance(parts[0], str) and len(parts) == 1:
            parts = [int(x) for x in parts[0].split(".")]
        elif isinstance(parts[0], int) and len(parts) == 1:
            parts = [(parts[0] & (0xff << i*8)) >> i*8 for i in range(3, -1, -1)] 
        elif len(parts) != 4:
            raise Exception(f"Unable to parse ip from {parts}")
        
        self.value = parts[0] << 24 | parts[1] << 16 | parts[2] << 8 | parts[3]
    
    def __int__(self):
        return self.value 

    def __str__(self):
        return f"{(self.value & 0xff000000) >> 24}.{(self.value & 0x00ff0000) >> 16}.{(self.value & 0x0000ff00) >> 8}.{self.value & 0x000000ff}"

    def __sub__(self, other):
        return self.value - other.value 


# INCLUSIVE 
class IP4Range:
    def __init__(self, start, end):
        start = IP4Address(start)
        end = IP4Address(end)

        if int(end) < int(start):
            raise Exception("End ip address smaller than start ip address")

        self.current = int(start) - 1
        self.end = int(end)
    
    def __iter__(self):
        return self

    def __next__(self):
        self.current += 1
        if self.current <= self.end:
            return IP4Address(self.current)

        raise StopIteration

    def __len__(self):
        return self.end - self.current - 1


            
